﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
using static System.Net.Mime.MediaTypeNames;
using System.Globalization;

namespace AllInOne.HDI.CRT_591_M001
{
    /// <summary>
    /// 发卡机支持的波特率
    /// </summary>
    public enum Baudrate
    {
        _9600BPS = 9600,
        _19200BPS = 19200,
        _38400BPS = 38400,
        _57600BPS = 57600
    }

    /// <summary>
    /// CRT_591_M001控制库
    /// </summary>
    public static class GrantCardClient
    {
        /// <summary>
        /// 错误字代码表
        /// 来源:文档【CRT_591_M001_通讯协议PDF.pdf】第12页
        /// </summary>
        static Dictionary<string, string> dic = new Dictionary<string, string>();

        //状态代码信息



        /// <summary>
        /// 函数:CommOpen
        /// 名称:打开串口
        /// </summary>
        /// <param name="port">串口号</param>
        /// <returns>>=0为成功，其它失败</returns>
        public static UInt32 CommOpen(string port)
        {
            if (dic.Count == 0)
            {
                dic.Add("00", "未定义的命令");
                dic.Add("01", "命令参数有错误");
                dic.Add("02", "命令执行顺序错误");
                dic.Add("03", "硬件不支持命令");
                dic.Add("04", "命令数据错误（通讯包中DATA有错误）");
                dic.Add("05", "IC卡接触未释放");
                dic.Add("10", "卡堵塞");
                dic.Add("12", "传感器错误");
                dic.Add("13", "长卡错误");
                dic.Add("14", "短卡错误");
                dic.Add("40", "回收卡时卡片被拔走");
                dic.Add("41", "IC卡电磁铁错误");
                dic.Add("43", "卡片不能移动卡IC卡位");
                dic.Add("45", "卡片被人为移动");
                dic.Add("50", "收卡计数器溢出");
                dic.Add("51", "马达错误");
                dic.Add("60", "IC卡供电电源短路");
                dic.Add("61", "IC卡激活失败");
                dic.Add("62", "IC卡不支持当前命令");
                dic.Add("65", "IC卡未激活");
                dic.Add("66", "当前IC卡不支持命令");
                dic.Add("67", "传输IC卡数据错误");
                dic.Add("68", "传输IC卡数据超时");
                dic.Add("69", "CPU/SAM卡不符合EMV标准");
                dic.Add("A0", "发卡卡栈(箱)空;卡栈中无卡(新增错误字)");
                dic.Add("A1", "收卡箱满(新增错误字)");
                dic.Add("B0", "卡机未复位");
            }
            return GrantCardSDK.CommOpen(port);
        }

        /// <summary>
        /// 函数:CommOpenWithBaut
        /// 名称:按指定的波特率打开串口
        /// </summary>
        /// <param name="port">串口号</param>
        /// <param name="Baudrate">波特率</param>
        /// <returns>>=0为成功，其它失败</returns>
        public static UInt32 CommOpenWithBaut(string port, UInt32 Baudrate)
        {
            return GrantCardSDK.CommOpenWithBaut(port, Baudrate);
        }

        /// <summary>
        /// 函数:CommClose
        /// 名称:关闭串口
        /// </summary>
        /// <param name="ComHandle">串口号</param>
        /// <returns></returns>
        public static int CommClose(UInt32 ComHandle)
        {
            return GrantCardSDK.CommClose(ComHandle);
        }

        /// <summary>
        /// 函数:ExecuteCommand
        /// 名称:执行命令函数
        /// </summary>
        /// <param name="ComHandle">串口号</param>
        /// <param name="TxAddr">卡机地址</param>
        /// <param name="TxCmCode">命令码</param>
        /// <param name="TxPmCode">操作码</param>
        /// <param name="TxDataLen">数据长度</param>
        /// <param name="TxData">数据内容</param>
        /// <param name="RxReplyType"></param>
        /// <param name="RxStCode0"></param>
        /// <param name="RxStCode1"></param>
        /// <param name="RxStCode2"></param>
        /// <param name="RxDataLen"></param>
        /// <param name="RxData"></param>
        /// <returns></returns>
        //int APIENTRY ExecuteCommand(HANDLE ComHandle,BYTE TxAddr,BYTE TxCmCode,BYTE TxPmCode,int TxDataLen,BYTE TxData[],BYTE *RxReplyType,BYTE *RxStCode0,BYTE *RxStCode1,BYTE *RxStCode2,int *RxDataLen,BYTE RxData[]);

        public static int ExecuteCommand(UInt32 ComHandle, byte TxAddr, byte TxCmCode, byte TxPmCode, UInt16 TxDataLen, byte[] TxData, ref byte RxReplyType, ref byte RxStCode0, ref byte RxStCode1, ref byte RxStCode2, ref UInt16 RxDataLen, byte[] RxData)
        {
            //byte RxReplyType, ref byte , ref byte , ref byte , ref UInt16 
            //RxReplyType =new byte { 0x0};
            //RxStCode0 = new byte { 0x0 };
            //RxStCode1 = new byte { 0x0 };
            //RxStCode2 = new byte { 0x0 };
            //RxDataLen = 0;

            return 0;
        }

        #region 自定义用到的相应操作

        //对收发卡一体机操作的封装Dll说明
        //1.主要根据厂家提供的代码方法进行处理
        //2.对操作后的结果进行返回
        //3.记录通信过程中发送的命令代码

        /// <summary>
        /// status 将状态信息转换成文字
        /// </summary>
        /// <returns></returns>
        public static string ToStatusCodeInfo(char st0, char st1, char st2)
        {
            string msg = "";
            switch (st0)
            {
                case '0':
                    msg += "卡机通道内无卡;";
                    break;
                case '1':
                    msg += "卡机通道出卡口处有一张卡;";
                    break;
                case '2':
                    msg += "卡机通道 PC/SC 卡位有卡;";
                    break;
                default:
                    msg += "st0:" + st0.ToString() + ";";
                    break;
            }
            switch (st1)
            {
                case '0':
                    msg += "发卡箱无卡;";
                    break;
                case '1':
                    msg += "发卡箱卡少;";
                    break;
                case '2':
                    msg += "发卡箱卡足;";
                    break;
                default:
                    msg += "st1:" + st1.ToString() + ";";
                    break;
            }
            switch (st2)
            {
                case '0':
                    msg += "回收箱未满;";
                    break;
                case '1':
                    msg += "回收箱卡满;";
                    break;
                default:
                    msg += "st2:" + st2.ToString();
                    break;
            }
            return msg;
        }
        /// <summary>
        /// error 将状态信息转换成文字
        /// </summary>
        /// <returns></returns>
        public static string ToErrorInfo(string ee)
        {
            if (dic.ContainsKey(ee))
            {
                return dic[ee];//返回错误代码的说明
            }
            else
            {
                return "未定义的错误代码返回";
            }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public static bool InitCard(UInt32 Hdle, string AddrComb, out string msg)
        {
            bool result = false;
            msg = "出错";
            if (Hdle != 0)
            {
                byte Addr;
                byte Cm, Pm;
                UInt16 TxDataLen, RxDataLen;
                byte[] TxData = new byte[1024];
                byte[] RxData = new byte[1024];
                byte ReType = 0;
                byte St0, St1, St2;

                Cm = 0x30;
                Pm = 0x30;
                St0 = St1 = St2 = 0;
                TxDataLen = 0;
                RxDataLen = 0;

                Addr = (byte)(byte.Parse(AddrComb.Substring(0, 2), NumberStyles.Number));
                int i = GrantCardSDK.ExecuteCommand(Hdle, Addr, Cm, Pm, TxDataLen, TxData, ref ReType, ref St0, ref St1, ref St2, ref RxDataLen, RxData);
                if (i == 0)
                {
                    if (ReType == 0x50)
                    {
                        //MessageBox.Show("INITIALIZE Successed" + "\r\n" + "Status Code : " + (char)St0 + (char)St1 + (char)St2, "INITIALIZE");
                        msg = "状态代码:" + (char)St0 + (char)St1 + (char)St2 + ",初始化:成功" + ",状态信息:" + ToStatusCodeInfo((char)St0, (char)St1, (char)St2);
                        result = true;
                    }
                    else
                    {
                        //MessageBox.Show("INITIALIZE ERROR" + "\r\n" + "Error Code:  " + (char)St1 + (char)St2, "INITIALIZE");
                        msg = "错误代码:" +(char)St1 + (char)St2 + ",初始化:失败" + ",错误信息:" + ToErrorInfo(((char)St1).ToString() + ((char)St2).ToString());
                        WriteLog(msg);
                    }
                }
                else
                {
                    ////MessageBox.Show("Communication Error", "Caution");
                    msg = "警告:通信错误";
                }
            }
            else
            {
                ////MessageBox.Show("Comm. port is not Opened", "Caution");
                msg = "警告:串口未打开";
            }
            return result;
        }


        /// <summary>
        /// 读取卡号
        /// </summary>
        /// <param name="Hdle">串口句柄</param>
        /// <param name="AddrComb">卡首地址</param>
        /// <param name="strCardUID">卡号</param>
        /// <param name="msg">命令执行结果信息</param>
        /// <returns></returns>
        public static bool MiCardActivate(UInt32 Hdle, string AddrComb, out string strCardUID, out string msg)
        {
            //必要说明，此读卡其实是，复位（激活）命令操作，用RF卡的物理卡号来作为RF卡的用户卡号
            bool result = false;
            msg = "出错";
            strCardUID = "";
            if (Hdle != 0)
            {
                byte Addr;
                byte Cm, Pm;
                UInt16 TxDataLen, RxDataLen;
                byte[] TxData = new byte[1024];
                byte[] RxData = new byte[1024];
                byte ReType = 0;
                byte St0, St1, St2;

                Cm = 0x60;
                Pm = 0x30;
                St0 = St1 = St2 = 0;
                TxDataLen = 2;
                RxDataLen = 0;

                TxData[0] = 0x41;
                TxData[1] = 0x42;
                Addr = (byte)(byte.Parse(AddrComb.Substring(0, 2), NumberStyles.Number));
                int i = GrantCardSDK.ExecuteCommand(Hdle, Addr, Cm, Pm, TxDataLen, TxData, ref ReType, ref St0, ref St1, ref St2, ref RxDataLen, RxData);
                if (i == 0)
                {
                    if (ReType == 0x50)
                    {
                        int n;
                        switch (RxData[0])
                        {
                            case 0x4d:  //mifare one Card
                                {
                                    string CardUID = "";
                                    for (n = 0; n < RxData[3]; n++)
                                    {
                                        CardUID = RxData[n + 4].ToString("X2") + CardUID;
                                    }
                                    strCardUID = CardUID;
                                    switch (RxData[2])
                                    {
                                        case 68: //Mifare one UL card
                                            {
                                                ////MessageBox.Show("Mifare one Card Activate Successed\nMifare one UL card ", "Activate RF Card");
                                                result = true;
                                                msg = "复位RF卡:Mifare one UL卡复位成功";
                                                break;
                                            }
                                        case 4: //Mifare one S50 card
                                            {
                                                ////MessageBox.Show("Mifare one Card Activate Successed\nMifare one S50 card ", "Activate RF Card");
                                                result = true;
                                                msg = "复位RF卡:Mifare one S50卡复位成功";
                                                break;
                                            }
                                        case 2: //Mifare one S70 card
                                            {
                                                ////MessageBox.Show("Mifare one Card Activate Successed\nMifare one S70 card ", "Activate RF Card");
                                                result = true;
                                                msg = "复位RF卡:Mifare one S70卡复位成功";
                                                break;
                                            }
                                    }
                                    ////MessageBox.Show("Mifare one Card Activate Successed\nCardUID: " + CardUID, "Activate RF Card");
                                    break;
                                }
                            case 0x41:   //type A card
                                {
                                    ////MessageBox.Show("type A Card Activate Successed ", "Activate RF Card");
                                    result = true;
                                    msg = "复位RF卡:type A卡复位成功";
                                    break;
                                }
                            case 0x42:   //type B card
                                {
                                    ////MessageBox.Show("type B Card Activate Successed ", "Activate RF Card");
                                    result = true;
                                    msg = "复位RF卡:type B卡复位成功";
                                    break;
                                }
                        }
                    }
                    else if ((ReType == 0x4e))
                    {
                        ///此错误应该是没有卡在读卡区位置而报的错误
                        ////MessageBox.Show("Activate RF Card ERROR" + "\r\n" + "Error Code:  " + (char)St1 + (char)St2, "Activate RF Card");                        
                        msg = "错误代码:" + (char)St1 + (char)St2 + ",复位RF卡:失败" + ",错误信息:" + ToErrorInfo(((char)St1).ToString() + ((char)St2).ToString());
                        WriteLog(msg);
                    }
                    else
                    {
                        ////MessageBox.Show("Communication Error", "Caution");
                        msg = "警告:通信错误";
                    }
                }
                else
                {
                    ////MessageBox.Show("Communication Error", "Caution");
                    msg = "警告:通信错误";
                }
            }
            else
            {
                ////MessageBox.Show("Communication Error", "Caution");
                msg = "警告:通信错误";
            }
            return result;
        }

        /// <summary>
        /// Mafare卡下电（释放）
        /// </summary>
        /// <param name="Hdle"></param>
        /// <param name="AddrComb"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool MiCardDactivate(UInt32 Hdle, string AddrComb, out string msg)
        {
            bool result = false;
            msg = "出错";
            if (Hdle != 0)
            {
                byte Addr;
                byte Cm, Pm;
                UInt16 TxDataLen, RxDataLen;
                byte[] TxData = new byte[1024];
                byte[] RxData = new byte[1024];
                byte ReType = 0;
                byte St0, St1, St2;

                Cm = 0x60;
                Pm = 0x31;
                St0 = St1 = St2 = 0;
                TxDataLen = 0;
                RxDataLen = 0;

                Addr = (byte)(byte.Parse(AddrComb.Substring(0, 2), NumberStyles.Number));
                int i = GrantCardSDK.ExecuteCommand(Hdle, Addr, Cm, Pm, TxDataLen, TxData, ref ReType, ref St0, ref St1, ref St2, ref RxDataLen, RxData);
                if (i == 0)
                {
                    if (ReType == 0x50)
                    {
                        // MessageBox.Show("Card Deactivate Successed", "Card Deactivate");
                        msg = "状态代码:" + (char)St0 + (char)St1 + (char)St2 + ",下电:成功" + ",状态信息:" + ToStatusCodeInfo((char)St0, (char)St1, (char)St2);
                        result = true;
                    }
                    else
                    {
                        //MessageBox.Show("Card Deactivate ERROR" + "\r\n" + "Error Code:  " + (char)St1 + (char)St2, "Card Deactivate");
                        msg = "错误代码:" + (char)St1 + (char)St2 + ",下电:失败" + ",错误信息:" + ToErrorInfo(((char)St1).ToString() + ((char)St2).ToString());
                        WriteLog(msg);
                    }

                }
                else
                {
                    ////MessageBox.Show("Communication Error", "Caution");
                    msg = "警告:通信错误";
                }
            }
            else
            {
                ////MessageBox.Show("Communication Error", "Caution");
                msg = "警告:串口未打开";
            }
            return result;
        }

        /// <summary>
        /// 获取卡状态
        /// </summary>
        /// <param name="Hdle"></param>
        /// <param name="AddrComb"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool CardStatus(UInt32 Hdle, string AddrComb, out string msg)
        {
            bool result = false;
            msg = "出错";
            if (Hdle != 0)
            {
                byte Addr;
                byte Cm, Pm;
                UInt16 TxDataLen, RxDataLen;
                byte[] TxData = new byte[1024];
                byte[] RxData = new byte[1024];
                byte ReType = 0;
                byte St0, St1, St2;

                Cm = 0x31;
                Pm = 0x30;
                St0 = St1 = St2 = 0;
                TxDataLen = 0;
                RxDataLen = 0;

                Addr = (byte)(byte.Parse(AddrComb.Substring(0, 2), NumberStyles.Number));
                int i = GrantCardSDK.ExecuteCommand(Hdle, Addr, Cm, Pm, TxDataLen, TxData, ref ReType, ref St0, ref St1, ref St2, ref RxDataLen, RxData);
                if (i == 0)
                {
                    if (ReType == 0x50)
                    {
                        ////MessageBox.Show("Card Status Successed" + "\r\n" + "Status Code : " + (char)St0 + (char)St1 + (char)St2, "Card Status");
                        result = true;
                        msg = "状态代码:" + (char)St0 + (char)St1 + (char)St2 + ",卡状态获取:成功" + ",状态信息:" + ToStatusCodeInfo((char)St0, (char)St1, (char)St2);
                    }
                    else
                    {
                        ////MessageBox.Show("Card Status ERROR" + "\r\n" + "Error Code:  " + (char)St1 + (char)St2, "Card Status");
                        msg = "错误代码:" + (char)St1 + (char)St2 + ",卡状态获取:失败" + ",错误信息:" + ToErrorInfo(((char)St1).ToString() + ((char)St2).ToString());
                        WriteLog(msg);
                    }
                }
                else
                {
                    ////MessageBox.Show("Communication Error", "Caution");
                    msg = "警告:通信错误";
                }
            }
            else
            {
                ////MessageBox.Show("Comm. port is not Opened", "Caution");
                msg = "警告:串口未打开";
            }
            return result;
        }

        /// <summary>
        /// 获取RF卡类型
        /// </summary>
        /// <param name="Hdle"></param>
        /// <param name="AddrComb"></param>
        /// <param name="RFType">卡类型</param>
        /// <param name="msg"></param>
        /// <returns>是否成功</returns>
        public static bool RFTestType(UInt32 Hdle, string AddrComb, out string RFType, out string msg)
        {
            bool result = false;
            msg = "出错";
            RFType = "";
            if (Hdle != 0)
            {
                byte Addr;
                byte Cm, Pm;
                UInt16 TxDataLen, RxDataLen;
                byte[] TxData = new byte[1024];
                byte[] RxData = new byte[1024];
                byte ReType = 0;
                byte St0, St1, St2;

                Cm = 0x50;
                Pm = 0x31;
                St0 = St1 = St2 = 0;
                TxDataLen = 0;
                RxDataLen = 0;

                Addr = (byte)(byte.Parse(AddrComb.Substring(0, 2), NumberStyles.Number));
                int i = GrantCardSDK.ExecuteCommand(Hdle, Addr, Cm, Pm, TxDataLen, TxData, ref ReType, ref St0, ref St1, ref St2, ref RxDataLen, RxData);
                if (i == 0)
                {
                    if (ReType == 0x50)
                    {
                        switch (RxData[0])
                        {
                            case 48:
                                switch (RxData[1])
                                {
                                    case 48:
                                        ////MessageBox.Show("Unknow Type", "RF Card Type");
                                        msg = "未知类型";
                                        break;
                                }
                                break;
                            case 49:
                                switch (RxData[1])
                                {
                                    case 48:
                                        ////MessageBox.Show("S50)", "RF Card Type");
                                        RFType = "S50";
                                        result = true;
                                        break;
                                    case 49:
                                        ////MessageBox.Show("S70", "RF Card Type");
                                        RFType = "S70";
                                        result = true;
                                        break;
                                    case 50:
                                        ////MessageBox.Show("UL CARD", "RF Card Type");
                                        RFType = "UL";
                                        result = true;
                                        break;
                                }
                                break;
                            case 50:
                                switch (RxData[1])
                                {
                                    case 48:
                                        ////MessageBox.Show("Type A CPU", "RF Card Type");
                                        RFType = "Type A";
                                        result = true;
                                        break;
                                }
                                break;
                            case 51:
                                switch (RxData[1])
                                {
                                    case 48:
                                        ////MessageBox.Show("Type B CPU", "RF Card Type");
                                        RFType = "Type B";
                                        result = true;
                                        break;
                                }
                                break;
                        }
                    }
                    else
                    {
                        ////MessageBox.Show("RF Card Type ERROR" + "\r\n" + "Error Code:  " + (char)St1 + (char)St2, "RF Card Type");
                        msg = "错误代码:" + (char)St1 + (char)St2 + ",获取RF卡类型:失败" + ",错误信息:" + ToErrorInfo(((char)St1).ToString() + ((char)St2).ToString());
                        WriteLog(msg);
                    }
                }
                else
                {
                    ////MessageBox.Show("Communication Error", "Caution");
                    msg = "警告:通信错误";
                }
            }
            else
            {
                ////MessageBox.Show("Comm. port is not Opened", "Caution");
                msg = "警告:串口未打开";
            }

            return result;
        }

        /// <summary>
        /// 获取IC卡类型
        /// </summary>
        /// <param name="Hdle"></param>
        /// <param name="AddrComb"></param>
        /// <param name="ICType">卡类型</param>
        /// <param name="msg"></param>
        /// <returns>是否成功</returns>
        public static bool ICTestType(UInt32 Hdle, string AddrComb, out string ICType, out string msg)
        {
            bool result = false;
            msg = "出错";
            ICType = "";
            if (Hdle != 0)
            {
                byte Addr;
                byte Cm, Pm;
                UInt16 TxDataLen, RxDataLen;
                byte[] TxData = new byte[1024];
                byte[] RxData = new byte[1024];
                byte ReType = 0;
                byte St0, St1, St2;

                Cm = 0x50;
                Pm = 0x30;/////、、
                St0 = St1 = St2 = 0;
                TxDataLen = 0;
                RxDataLen = 0;

                Addr = (byte)(byte.Parse(AddrComb.Substring(0, 2), NumberStyles.Number));
                int i = GrantCardSDK.ExecuteCommand(Hdle, Addr, Cm, Pm, TxDataLen, TxData, ref ReType, ref St0, ref St1, ref St2, ref RxDataLen, RxData);
                if (i == 0)
                {
                    if (ReType == 0x50)
                    {
                        switch (RxData[0])
                        {
                            case 48:
                                switch (RxData[1])
                                {
                                    case 48:
                                        //MessageBox.Show("Unknow Type", "IC Card Type");
                                        msg = "未知类型";
                                        break;
                                }
                                break;
                            case 49:
                                switch (RxData[1])
                                {
                                    case 48:
                                        ICType = "CPU CARD(T=0)";
                                        result = true;
                                        //MessageBox.Show("CPU CARD(T=0)", "IC Card Type");
                                        break;
                                    case 49:
                                        //MessageBox.Show("CPU CARD(T=1)", "IC Card Type");
                                        ICType = "CPU CARD(T=1)";
                                        result = true;
                                        break;
                                }
                                break;
                            case 50:
                                switch (RxData[1])
                                {
                                    case 48:
                                        ICType = "SLE4442";
                                        result = true;
                                        //MessageBox.Show("SLE4442", "IC Card Type");
                                        break;
                                    case 49:
                                        ICType = "SLE4428";
                                        result = true;
                                        //MessageBox.Show("SLE4428", "IC Card Type");
                                        break;
                                }
                                break;
                            case 51:
                                switch (RxData[1])
                                {
                                    case 48:
                                        //MessageBox.Show("24C01", "IC Card Type");
                                        ICType = "24C01";
                                        result = true;
                                        break;
                                    case 49:
                                        ICType = "24C02";
                                        result = true;
                                        //MessageBox.Show("24C02", "IC Card Type");
                                        break;
                                    case 50:
                                        ICType = "24C04";
                                        result = true;
                                        //MessageBox.Show("24C04", "IC Card Type");
                                        break;
                                    case 41:
                                        ICType = "24C08";
                                        result = true;
                                        //MessageBox.Show("24C08", "IC Card Type");
                                        break;
                                    case 42:
                                        ICType = "24C08";
                                        result = true;
                                        //MessageBox.Show("24C16", "IC Card Type");
                                        break;
                                    case 53:
                                        ICType = "24C32";
                                        result = true;
                                        //MessageBox.Show("24C32", "IC Card Type");
                                        break;
                                    case 54:
                                        ICType = "24C64";
                                        result = true;
                                        //MessageBox.Show("24C64", "IC Card Type");
                                        break;
                                    case 55:
                                        ICType = "24C128";
                                        result = true;
                                        //MessageBox.Show("24C128", "IC Card Type");
                                        break;
                                    case 56:
                                        ICType = "24C256";
                                        result = true;
                                        //MessageBox.Show("24C256", "IC Card Type");
                                        break;
                                }
                                break;
                        }
                    }
                    else
                    {
                        msg = "错误代码:" + (char)St1 + (char)St2 + ",获取IC卡类型:失败" + ",错误信息:" + ToErrorInfo(((char)St1).ToString() + ((char)St2).ToString());
                        //MessageBox.Show("IC Card Type ERROR" + "\r\n" + "Error Code:  " + (char)St1 + (char)St2, "IC Card Type");
                        WriteLog(msg);
                    }

                }
                else
                {
                    ////MessageBox.Show("Communication Error", "Caution");
                    msg = "警告:通信错误";
                }
            }
            else
            {
                ////MessageBox.Show("Comm. port is not Opened", "Caution");
                msg = "警告:串口未打开";
            }

            return result;
        }

        /// <summary>
        /// 允许进卡
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public static bool AllCardIn(UInt32 Hdle, string AddrComb, out string msg)
        {
            bool result = false;
            msg = "出错";
            if (Hdle != 0)
            {
                byte Addr;
                byte Cm, Pm;
                UInt16 TxDataLen, RxDataLen;
                byte[] TxData = new byte[1024];
                byte[] RxData = new byte[1024];
                byte ReType = 0;
                byte St0, St1, St2;

                Cm = 0x33;
                Pm = 0x30;
                St0 = St1 = St2 = 0;
                TxDataLen = 0;
                RxDataLen = 0;

                Addr = (byte)(byte.Parse(AddrComb.Substring(0, 2), NumberStyles.Number));
                int i = GrantCardSDK.ExecuteCommand(Hdle, Addr, Cm, Pm, TxDataLen, TxData, ref ReType, ref St0, ref St1, ref St2, ref RxDataLen, RxData);
                if (i == 0)
                {
                    if (ReType == 0x50)
                    {
                        //MessageBox.Show("Allowed card in Successed" + "\r\n" + "Status Code : " + (char)St0 + (char)St1 + (char)St2, "Allowed card in");
                        msg = "状态代码:" + (char)St0 + (char)St1 + (char)St2 + ",设置允许进卡:成功" + ",状态信息:" + ToStatusCodeInfo((char)St0, (char)St1, (char)St2);
                        result = true;
                    }
                    else
                    {
                        //MessageBox.Show("Allowed card in ERROR" + "\r\n" + "Error Code:  " + (char)St1 + (char)St2, "Allowed card in");
                        msg = "错误代码:" + (char)St1 + (char)St2 + ",设置允许进卡:失败" + ",错误信息:" + ToErrorInfo(((char)St1).ToString() + ((char)St2).ToString());
                        WriteLog(msg);
                    }

                }
                else
                {
                    //MessageBox.Show("Communication Error", "Caution");
                    msg = "警告:通信错误";
                }
            }
            else
            {
                //MessageBox.Show("Comm. port is not Opened", "Caution");
                msg = "警告:串口未打开";
            }
            return result;
        }

        /// <summary>
        /// 禁止进卡
        /// </summary>
        /// <param name="Hdle"></param>
        /// <param name="AddrComb"></param>
        /// <param name="msg"></param>
        public static bool NoCardIn(UInt32 Hdle, string AddrComb, out string msg)
        {
            bool result = false;
            msg = "出错";
            if (Hdle != 0)
            {
                byte Addr;
                byte Cm, Pm;
                UInt16 TxDataLen, RxDataLen;
                byte[] TxData = new byte[1024];
                byte[] RxData = new byte[1024];
                byte ReType = 0;
                byte St0, St1, St2;

                Cm = 0x33;
                Pm = 0x31;
                St0 = St1 = St2 = 0;
                TxDataLen = 0;
                RxDataLen = 0;

                Addr = (byte)(byte.Parse(AddrComb.Substring(0, 2), NumberStyles.Number));
                int i = GrantCardSDK.ExecuteCommand(Hdle, Addr, Cm, Pm, TxDataLen, TxData, ref ReType, ref St0, ref St1, ref St2, ref RxDataLen, RxData);
                if (i == 0)
                {
                    if (ReType == 0x50)
                    {
                        //MessageBox.Show("Prohibition card in Successed" + "\r\n" + "Status Code : " + (char)St0 + (char)St1 + (char)St2, "Prohibition card in");
                        msg = "状态代码:" + (char)St0 + (char)St1 + (char)St2 + ",设置禁止进卡:成功" + ",状态信息:" + ToStatusCodeInfo((char)St0, (char)St1, (char)St2);
                        result = true;
                    }
                    else
                    {
                        //MessageBox.Show("Prohibition card in ERROR" + "\r\n" + "Error Code:  " + (char)St1 + (char)St2, "Prohibition card in");
                        msg = "错误代码:" + (char)St1 + (char)St2 + ",设置禁止进卡:失败" + ",错误信息:" + ToErrorInfo(((char)St1).ToString() + ((char)St2).ToString());
                        WriteLog(msg);
                    }

                }
                else
                {
                    //MessageBox.Show("Communication Error", "Caution");
                    msg = "警告:通信错误";
                }
            }
            else
            {
                //MessageBox.Show("Comm. port is not Opened", "Caution");
                msg = "警告:串口未打开";
            }
            return result;
        }

        /// <summary>
        /// 移动卡操作:前端不持卡位
        /// </summary>
        /// <param name="Hdle"></param>
        /// <param name="AddrComb"></param>
        /// <param name="msg"></param>
        public static bool MoveCardToFront1(UInt32 Hdle, string AddrComb, out string msg)
        {
            bool result = false;
            msg = "出错";
            if (Hdle != 0)
            {
                byte Addr;
                byte Cm, Pm;
                UInt16 TxDataLen, RxDataLen;
                byte[] TxData = new byte[1024];
                byte[] RxData = new byte[1024];
                byte ReType = 0;
                byte St0, St1, St2;

                Cm = 0x32;
                Pm = 0x39;
                St0 = St1 = St2 = 0;
                TxDataLen = 0;
                RxDataLen = 0;

                Addr = (byte)(byte.Parse(AddrComb.Substring(0, 2), NumberStyles.Number));
                int i = GrantCardSDK.ExecuteCommand(Hdle, Addr, Cm, Pm, TxDataLen, TxData, ref ReType, ref St0, ref St1, ref St2, ref RxDataLen, RxData);
                if (i == 0)
                {
                    if (ReType == 0x50)
                    {
                        //MessageBox.Show("Move Card Successed" + "\r\n" + "Status Code : " + (char)St0 + (char)St1 + (char)St2, "Move Card");
                        result = true;
                        msg = "状态代码:" + (char)St0 + (char)St1 + (char)St2 + ",移动卡操作 前端不持卡位:成功" + ",状态信息:" + ToStatusCodeInfo((char)St0, (char)St1, (char)St2);

                    }
                    else
                    {
                        //MessageBox.Show("Move Card ERROR" + "\r\n" + "Error Code:  " + (char)St1 + (char)St2, "Move Card");
                        msg = "错误代码:" + (char)St1 + (char)St2 + ",移动卡操作 前端不持卡位:失败" + ",错误信息:" + ToErrorInfo(((char)St1).ToString() + ((char)St2).ToString());
                        WriteLog(msg);
                    }
                }
                else
                {
                    //MessageBox.Show("Communication Error", "Caution");
                    msg = "警告:通信错误";
                }
            }
            else
            {
                //MessageBox.Show("Comm. port is not Opened", "Caution");
                msg = "警告:串口未打开";
            }
            return result;
        }

        /// <summary>
        /// 移动卡操作:前端持卡位
        /// </summary>
        /// <param name="Hdle"></param>
        /// <param name="AddrComb"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool MoveCardToFront2(UInt32 Hdle, string AddrComb, out string msg)
        {
            bool result = false;
            msg = "出错";
            if (Hdle != 0)
            {
                byte Addr;
                byte Cm, Pm;
                UInt16 TxDataLen, RxDataLen;
                byte[] TxData = new byte[1024];
                byte[] RxData = new byte[1024];
                byte ReType = 0;
                byte St0, St1, St2;

                Cm = 0x32;
                Pm = 0x30;
                St0 = St1 = St2 = 0;
                TxDataLen = 0;
                RxDataLen = 0;

                Addr = (byte)(byte.Parse(AddrComb.Substring(0, 2), NumberStyles.Number));
                int i = GrantCardSDK.ExecuteCommand(Hdle, Addr, Cm, Pm, TxDataLen, TxData, ref ReType, ref St0, ref St1, ref St2, ref RxDataLen, RxData);
                if (i == 0)
                {
                    if (ReType == 0x50)
                    {
                        //MessageBox.Show("Move Card Successed" + "\r\n" + "Status Code : " + (char)St0 + (char)St1 + (char)St2, "Move Card");
                        msg = "状态代码:" + (char)St0 + (char)St1 + (char)St2 + ",移动卡操作 前端持卡位:成功" + ",状态信息:" + ToStatusCodeInfo((char)St0, (char)St1, (char)St2);

                        result = true;
                    }
                    else
                    {
                        //MessageBox.Show("Move Card ERROR" + "\r\n" + "Error Code:  " + (char)St1 + (char)St2, "Move Card");
                        msg = "错误代码:" + (char)St1 + (char)St2 + ",移动卡操作 前端持卡位:失败" + ",错误信息:" + ToErrorInfo(((char)St1).ToString() + ((char)St2).ToString());
                        WriteLog(msg);
                    }
                }
                else
                {
                    msg = "警告:通信错误";
                }
            }
            else
            {
                msg = "警告:串口未打开";
            }
            return result;
        }

        /// <summary>
        /// 移动卡操作:RF位置
        /// </summary>
        /// <param name="Hdle"></param>
        /// <param name="AddrComb"></param>
        /// <param name="msg"></param>
        public static bool MoveCardToRF(UInt32 Hdle, string AddrComb, out string msg)
        {
            bool result = false;
            msg = "出错";
            if (Hdle != 0)
            {
                byte Addr;
                byte Cm, Pm;
                UInt16 TxDataLen, RxDataLen;
                byte[] TxData = new byte[1024];
                byte[] RxData = new byte[1024];
                byte ReType = 0;
                byte St0, St1, St2;

                Cm = 0x32;
                Pm = 0x32;
                St0 = St1 = St2 = 0;
                TxDataLen = 0;
                RxDataLen = 0;

                Addr = (byte)(byte.Parse(AddrComb.Substring(0, 2), NumberStyles.Number));
                int i = GrantCardSDK.ExecuteCommand(Hdle, Addr, Cm, Pm, TxDataLen, TxData, ref ReType, ref St0, ref St1, ref St2, ref RxDataLen, RxData);
                if (i == 0)
                {
                    if (ReType == 0x50)
                    {
                        //MessageBox.Show("Move Card Successed" + "\r\n" + "Status Code : " + (char)St0 + (char)St1 + (char)St2, "Move Card");
                        msg = "状态代码:" + (char)St0 + (char)St1 + (char)St2 + ",移动卡操作 RF位置:成功" + ",状态信息:" + ToStatusCodeInfo((char)St0, (char)St1, (char)St2);

                        result = true;
                    }
                    else
                    {
                        //MessageBox.Show("Move Card ERROR" + "\r\n" + "Error Code:  " + (char)St1 + (char)St2, "Move Card");
                        msg = "错误代码:" + (char)St1 + (char)St2 + ",移动卡操作 RF位置:失败" + ",错误信息:" + ToErrorInfo(((char)St1).ToString() + ((char)St2).ToString());
                        WriteLog(msg);
                    }
                }
                else
                {
                    msg = "警告:通信错误";
                }
            }
            else
            {
                msg = "警告:串口未打开";
            }
            return result;
        }







        /// <summary>
        /// 移动卡操作:IC位置
        /// </summary>
        /// <param name="Hdle"></param>
        /// <param name="AddrComb"></param>
        /// <param name="msg"></param>
        public static bool MoveCardToICCBtn_Click(UInt32 Hdle, string AddrComb, out string msg)
        {
            bool result = false;
            msg = "出错";
            if (Hdle != 0)
            {
                byte Addr;
                byte Cm, Pm;
                UInt16 TxDataLen, RxDataLen;
                byte[] TxData = new byte[1024];
                byte[] RxData = new byte[1024];
                byte ReType = 0;
                byte St0, St1, St2;

                Cm = 0x32;
                Pm = 0x31;
                St0 = St1 = St2 = 0;
                TxDataLen = 0;
                RxDataLen = 0;

                Addr = (byte)(byte.Parse(AddrComb.Substring(0, 2), NumberStyles.Number));
                int i = GrantCardSDK.ExecuteCommand(Hdle, Addr, Cm, Pm, TxDataLen, TxData, ref ReType, ref St0, ref St1, ref St2, ref RxDataLen, RxData);
                if (i == 0)
                {
                    if (ReType == 0x50)
                    {
                        //MessageBox.Show("Move Card Successed" + "\r\n" + "Status Code : " + (char)St0 + (char)St1 + (char)St2, "Move Card");
                        msg = "移动卡操作:IC位置，成功，状态代码:" + (char)St0 + (char)St1 + (char)St2;
                        result = true;
                    }
                    else
                    {
                        //MessageBox.Show("Move Card ERROR" + "\r\n" + "Error Code:  " + (char)St1 + (char)St2, "Move Card");
                        msg = "移动卡操作:IC位置，失败，错误代码:" + (char)St1 + (char)St2;
                        WriteLog(msg);
                    }
                }
                else
                {
                    msg = "警告:通信错误";
                }
            }
            else
            {
                msg = "警告:串口未打开";
            }
            return result;
        }

        /// <summary>
        /// 移动卡操作:回收盒
        /// </summary>
        /// <param name="Hdle"></param>
        /// <param name="AddrComb"></param>
        /// <param name="msg"></param>
        public static bool MoveCardToRecycleBin(UInt32 Hdle, string AddrComb, out string msg)
        {
            bool result = false;
            msg = "出错";
            if (Hdle != 0)
            {
                byte Addr;
                byte Cm, Pm;
                UInt16 TxDataLen, RxDataLen;
                byte[] TxData = new byte[1024];
                byte[] RxData = new byte[1024];
                byte ReType = 0;
                byte St0, St1, St2;

                Cm = 0x32;
                Pm = 0x33;
                St0 = St1 = St2 = 0;
                TxDataLen = 0;
                RxDataLen = 0;

                Addr = (byte)(byte.Parse(AddrComb.Substring(0, 2), NumberStyles.Number));
                int i = GrantCardSDK.ExecuteCommand(Hdle, Addr, Cm, Pm, TxDataLen, TxData, ref ReType, ref St0, ref St1, ref St2, ref RxDataLen, RxData);
                if (i == 0)
                {
                    if (ReType == 0x50)
                    {
                        //MessageBox.Show("Move Card Successed" + "\r\n" + "Status Code : " + (char)St0 + (char)St1 + (char)St2, "Move Card");
                        msg = "状态代码:" + (char)St0 + (char)St1 + (char)St2 + ",移动卡操作 回收盒:成功" + ",状态信息:" + ToStatusCodeInfo((char)St0, (char)St1, (char)St2);
                        result = true;
                    }
                    else
                    {
                        //MessageBox.Show("Move Card ERROR" + "\r\n" + "Error Code:  " + (char)St1 + (char)St2, "Move Card");
                        msg = "错误代码:" + (char)St1 + (char)St2 + ",移动卡操作 回收盒:失败" + ",错误信息:" + ToErrorInfo(((char)St1).ToString() + ((char)St2).ToString());
                        WriteLog(msg);
                    }
                }
                else
                {
                    msg = "警告:通信错误";
                }
            }
            else
            {
                msg = "警告:串口未打开";
            }
            return result;
        }
        
        #endregion

        #region 读写日志文件
        public static void WriteLog(string content)
        {
            string path = GetCurrentPath("log/log_01_发卡机");
            //判断log文件夹是否存在
            if (path.Length == 0)
            {
                Directory.CreateDirectory(path);
            }
            string time = FormatDate(DateTime.Now);
            path = AddNewLog(path, time);
            try
            {
                FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
                using (StreamWriter sw = new StreamWriter(fs, Encoding.Default))
                {
                    sw.Flush();
                    //设置写入的位置,第一个参数是相对于第二个参数的偏移量
                    sw.BaseStream.Seek(0, SeekOrigin.End);
                    //把richTextBox1中的内容写入文件
                    sw.WriteLine("【" + DateTime.Now.ToString() + "】" + content);
                    //关闭此文件
                    sw.Flush();
                    sw.Close();
                }
                fs.Close();
                fs.Dispose();
            }
            catch
            {
                System.Threading.Thread.Sleep(10);
            }

        }
        public static string FormatDate(DateTime dTime)
        {
            string rStr;
            rStr = dTime.ToString("yyyyMMdd"); ;
            return rStr;
        }
        /// <summary>
        /// 获取当前路径(相对应程序)信息,支持文件夹
        /// </summary>
        /// <param name="path">短路径(前无\\)</param>
        /// <returns>全路径</returns>
        public static string GetCurrentPath(string path)
        {
            //获取和设置当前目录（即该进程从中启动的目录）的完全限定路径
            path = Environment.CurrentDirectory + "\\" + path;
            bool directoryFlag = Directory.Exists(path);
            if (directoryFlag)
            {
                return path;
            }
            else
            {
                Directory.CreateDirectory(path);
            }
            return path;
        }

        /// <summary>
        /// 添加日志索引
        /// </summary>
        /// <param name="path">日志目录</param>
        /// <param name="time">日期</param>
        /// <returns></returns>
        private static string AddNewLog(string path, string time)
        {
            path = path + "\\" + time + ".dat";
            if (!File.Exists(path))
            {
                List<string> datStrs = new List<string>();
                try
                {
                    datStrs.Add(time);
                    string newPath = path.Replace(time + ".dat", "new.dat");
                    FileStream fs = new FileStream(newPath, FileMode.OpenOrCreate, FileAccess.Read);
                    using (StreamReader sr = new StreamReader(fs, Encoding.Default))
                    {
                        while (sr.Peek() > 0)
                        {
                            datStrs.Add(sr.ReadLine());
                        }
                        sr.Close();
                        sr.Dispose();
                    }
                    fs.Close();
                    fs = new FileStream(newPath, FileMode.OpenOrCreate, FileAccess.Write);
                    if (datStrs.Count > 5)
                    {
                        for (int i = datStrs.Count - 1; i > 4; i++)
                        {
                            datStrs.RemoveAt(i);
                        }
                    }
                    using (StreamWriter sw = new StreamWriter(fs, Encoding.Default))
                    {
                        sw.Flush();
                        //设置写入的位置,第一个参数是相对于第二个参数的偏移量
                        sw.BaseStream.Seek(0, SeekOrigin.Begin);
                        foreach (string dataStr in datStrs)
                        {
                            sw.WriteLine(dataStr);
                        }
                        //关闭此文件
                        sw.Flush();
                        sw.Close();
                    }
                    fs.Close();
                }
                catch
                {
                    System.Threading.Thread.Sleep(10);
                }
            }
            return path;
        }
        #endregion
    }
}